package org.dei.perla.sys.console;


import java.io.*;
import java.net.Socket;
import org.dei.perla.parser.grammar.Parser;
import org.dei.perla.sys.console.ConsoleMessage.*;
import org.dei.perla.sys.console.ConsoleMessage.PerLaResponse.ResultType;

/**
 * Per ogni richiesta di connessione viene generato un Thread
 * rappresentato da questa classe.
 * @author diego
 */
class ServerThread implements Runnable {

	/**
	 * Il socket che verra' usato per la connessione
	 */
	private Socket pSocket;
	
	/**
	 * Costruttore
	 * @param parSocket
	 */
	ServerThread(Socket parSocket) {
		this.pSocket = parSocket;
		}
	
	/**
	 * Metodo per far partire l'attivita' 
	 */
	public void run() {
		
		boolean tConnectionOpened = true;
		
		try {
			
			//...fino a quando non arriva il segnale di connessione da terminare...
			while (tConnectionOpened) {					
				
				//...Ricevo la richiesta...
				PerLaRequest tRequest = ConsoleUtils.receiveRequest(pSocket);				
								
				System.out.println("Controllo integrita' \n");
				
				if (!tRequest.isInitialized()) {
				 System.out.println("Errore nel messaggio \n");
				 }else {System.out.println("Il messaggio e' OK \n");}

				//Recupero l'header e agisco di conseguenza
				switch (tRequest.getRequestHeader()) {
					case TEST_QUERY : testQuery(tRequest.getTestQueryRequestMessage().getQueryToTest());						
					case STOP_QUERY : tConnectionOpened = false;			
				
				}
				
				//..controllo che il client non abbia chiuso la connessione, altrimenti termino
				
				if (!this.pSocket.isConnected()) tConnectionOpened = false;
				
				
			}
		
		} catch (Exception e) {
			System.out.println("Errore nel server");
			e.printStackTrace();
		}
		
		//...qui la connessione e' stata chiusa, agisco di conseguenza.
		try {
			this.finalize();		
		} catch (Throwable e) {
			System.out.println("Errore nella chiusura del server...\n");		
		}
		System.out.println("Questo ServerThread ha terminato, addio....\n");
		
	}
		
	
	/**
	 * Metodo privato interno per gestire il test della query
	 * @param message
	 */
	private void testQuery(String message) {
		
		//...comincio a recuperare la query...
		byte []bytes = message.getBytes();
		
		//...preparo il builder per una risposta (sia errore, che ok)
		ConsoleMessage.PerLaResponse.Builder messageResponseBuilder = ConsoleMessage.PerLaResponse.newBuilder();
		TestQueryMessage.TestQueryResponse.Builder testQueryResponseBuilder = TestQueryMessage.TestQueryResponse.newBuilder();
		
		//...a questo punto provo a parsare...
		boolean firststart = false;			
		if (firststart == false) {
			firststart = true;						
			new Parser(new ByteArrayInputStream(bytes));
		}else Parser.ReInit(new ByteArrayInputStream(bytes));
		
		try {						
			Parser.StatementSequence();
			
			//il parsing non ha generato errore, quindi posso inviare l'OK
			messageResponseBuilder.setResponseHeader(ResultType.OK);
			testQueryResponseBuilder.setQueryError("NO ERROR...");
			messageResponseBuilder.setTestQueryResponseMessage(testQueryResponseBuilder.build());
			
			
		} 
		catch (Exception e) {
			
			//il parsing ha dato qualche errore, NOT OK
			messageResponseBuilder.setResponseHeader(ResultType.ERROR);
			testQueryResponseBuilder.setQueryError(e.getMessage());
			messageResponseBuilder.setTestQueryResponseMessage(testQueryResponseBuilder.build());			
			
		}
		
		//...qualsiasi sia stato l'esito... invio...
		ConsoleUtils.sendResponse(messageResponseBuilder.build(),this.pSocket);
	
	}
}
